import { IExtent } from '@/types/position'
import { useDebounceFn } from '@vueuse/core'
import { onBeforeUnmount } from 'vue'

type IViewerChangeFn = (extend: IExtent) => void

function useCesiumViewerChange(debounceTime: number = 1000) {
    let viewer: Cesium.Viewer | null = null

    let viewerChangeFn: IViewerChangeFn | null = null

    function onViewerChange(fn: IViewerChangeFn) {
        viewerChangeFn = fn
    }

    const debounceChange = useDebounceFn((extend: IExtent) => {
        if (viewerChangeFn) {
            viewerChangeFn(extend)
        }
    }, debounceTime)

    function viewerChangeEventHandler() {
        const params = getCesiumViewerExtend(viewer!)
        debounceChange(params)
    }

    function initViewerChange(_viewer: Cesium.Viewer) {
        // viewer = viewer

        viewer = _viewer

        _viewer.camera.changed.addEventListener(viewerChangeEventHandler)
    }

    function getCesiumViewerExtend(viewer: Cesium.Viewer) {
        const params: IExtent = {
            maxx: 0,
            maxy: 0,
            minx: 0,
            miny: 0,
        }
        // computeViewRectangle,计算椭球上的近似可见矩形（返回 Rectangle），如果椭圆形根本不可见，则返回undefined。
        const extend = viewer.camera.computeViewRectangle()
        if (typeof extend === 'undefined') {
            //2D下会可能拾取不到坐标，extend返回undefined,所以做以下转换
            const canvas = viewer.scene.canvas
            const upperLeft = new Cesium.Cartesian2(0, 0) //canvas左上角坐标转2d坐标
            const lowerRight = new Cesium.Cartesian2(
                canvas.clientWidth,
                canvas.clientHeight,
            ) //canvas右下角坐标转2d坐标

            const ellipsoid = viewer.scene.globe.ellipsoid
            const upperLeft3 = viewer.camera.pickEllipsoid(upperLeft, ellipsoid) //2D转3D世界坐标

            const lowerRight3 = viewer.camera.pickEllipsoid(
                lowerRight,
                ellipsoid,
            ) //2D转3D世界坐标

            const upperLeftCartographic =
                viewer.scene.globe.ellipsoid.cartesianToCartographic(
                    upperLeft3!,
                ) //3D世界坐标转弧度
            const lowerRightCartographic =
                viewer.scene.globe.ellipsoid.cartesianToCartographic(
                    lowerRight3!,
                ) //3D世界坐标转弧度

            const minx = Cesium.Math.toDegrees(upperLeftCartographic.longitude) //弧度转经纬度
            const maxx = Cesium.Math.toDegrees(lowerRightCartographic.longitude) //弧度转经纬度

            const miny = Cesium.Math.toDegrees(lowerRightCartographic.latitude) //弧度转经纬度
            const maxy = Cesium.Math.toDegrees(upperLeftCartographic.latitude) //弧度转经纬度

            params.minx = minx // 最小经度
            params.maxx = maxx // 最大经度
            params.miny = miny // 最小纬度
            params.maxy = maxy // 最大纬度
        } else {
            //3D获取方式
            // 最大经度
            params.maxx = Cesium.Math.toDegrees(extend.east) //弧度转经纬度
            // 最大纬度
            params.maxy = Cesium.Math.toDegrees(extend.north) //弧度转经纬度
            // 最小经度
            params.minx = Cesium.Math.toDegrees(extend.west) //弧度转经纬度
            // 最小纬度
            params.miny = Cesium.Math.toDegrees(extend.south) //弧度转经纬度
        }
        return params //返回屏幕所在经纬度范围
    }

    onBeforeUnmount(() => {
        if (viewer) {
            viewer.camera.changed.removeEventListener(viewerChangeEventHandler)
        }
    })

    return {
        onViewerChange,
        initViewerChange,
    }
}

export default useCesiumViewerChange
